package com.linghang.wusthelper.util;

import com.linghang.wusthelper.entity.primary.Grade;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;

/**
 * @author origin
 * 加密及hash算法工具类
 */
public class EncryptUtil {

    //  教务处密码对称秘钥
    //  对称加密生成秘钥需要的种子   勿泄漏！！！！
    //  上线后不要更改，否则无法完成学生密码解密
    //  如要更改需要把数据库所有密码解密后，再用新秘钥加密一遍
    private static final String MiddleKey = "wusthelperlh";

    //  课表分享对称加解密秘钥
    private static final String decryptKey = "lhylwlyfqh121380";

    private static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    private static Key converSecretKey;

    /**
     * 获取成绩hash
     * @param grade
     * @return
     */
    public static String getGradeHash(Grade grade){
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.update(grade.getStuNum().getBytes());
            messageDigest.update(grade.getStuName().getBytes());
            messageDigest.update(grade.getSchoolTerm().getBytes());
            messageDigest.update(grade.getCourseName().getBytes());
            messageDigest.update(grade.getGrade().getBytes());
            messageDigest.update(grade.getCourseNature().getBytes());
            messageDigest.update(grade.getCourseCategory().getBytes());
            messageDigest.update(String.valueOf(grade.getCourseHours()).getBytes());
            messageDigest.update(String.valueOf(grade.getCourseCredit()).getBytes());
            messageDigest.update(grade.getExamNature().getBytes());
            byte[] encryptStr = messageDigest.digest();
            // 获得密文完成哈希计算,产生128 位的长整数
            char str[] = new char[16 * 2];
            // 每个字节用 16 进制表示的话，使用两个字符
            int k = 0;
            // 表示转换结果中对应的字符位置
            for (int i = 0; i < 16; i++) {
                // 从第一个字节开始，对每一个字节,转换成 16 进制字符的转换
                byte byte0 = encryptStr[i];
                // 取第 i 个字节
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                // 取字节中高 4 位的数字转换, >>> 为逻辑右移，将符号位一起右移
                str[k++] = hexDigits[byte0 & 0xf];
                // 取字节中低 4 位的数字转换
            }
            return new String(str);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 密码加密
     * @param password
     * @return
     */
    public static String encryptPasswd(String password){
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE,getConverSecretKey());
            byte[] result = cipher.doFinal(password.getBytes());
            //  通过Base64转码返回
            return Base64.encodeBase64String(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 密码解密
     * @param encryptedPassword
     * @return
     */
    public static String decryptPasswd(String encryptedPassword){
        try {
            Cipher cipher = Cipher.getInstance("/AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, getConverSecretKey());
            byte[] result = cipher.doFinal(Base64.decodeBase64(encryptedPassword));
            return new String(result);
        }catch (Exception e){
            e.printStackTrace();
        }
        return "";
     }

    /**
     * 获取秘钥
     * @return
     */
    public static Key getConverSecretKey() {
        if (converSecretKey == null){
            try {
                //  生成KEY,AES  要求秘钥长度为128
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
                secureRandom.setSeed(MiddleKey.getBytes());
                keyGenerator.init(128,secureRandom);
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] byteKey = secretKey.getEncoded();

                //  转换key
                converSecretKey = new SecretKeySpec(byteKey,"AES");
                return converSecretKey;
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        return converSecretKey;
    }

    /**
     * AES加密
     * @param content 待加密的内容
     * @return 加密后的byte[]
     * @throws Exception
     */
    public static String aesEncryptToBytes(String content) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
        return Base64.encodeBase64String(cipher.doFinal(content.getBytes("utf-8")));
    }

    /**
     * AES解密
     * @param encryptBytes 待解密的byte[]
     * @return 解密后的String
     * @throws Exception
     */
    public static String aesDecryptByBytes(String encryptBytes) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128);
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
        byte[] decryptBytes = cipher.doFinal(Base64.decodeBase64(encryptBytes));
        return new String(decryptBytes);
    }
}
